package com.ray.system.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ray.common.SysMsgCodeConstant;
import com.ray.system.builder.CommonPageBuilder;
import com.ray.system.builder.RoleBuilder;
import com.ray.system.builder.UserMenuBuilder;
import com.ray.system.check.AppCheck;
import com.ray.system.check.MenuCheck;
import com.ray.system.check.RoleCheck;
import com.ray.system.service.*;
import com.ray.system.table.dto.RoleQueryDTO;
import com.ray.system.table.entity.SysApp;
import com.ray.system.table.entity.SysMenu;
import com.ray.system.table.entity.SysRole;
import com.ray.system.table.entity.SysUserRole;
import com.ray.system.table.params.role.*;
import com.ray.system.table.vo.role.RoleVO;
import com.ray.validate.support.utils.ValidateUtil;
import com.ray.woodencreate.beans.LoginUser;
import com.ray.woodencreate.enums.YesOrNoEnum;
import com.ray.woodencreate.exception.BusinessExceptionFactory;
import com.ray.woodencreate.page.CommonPage;
import com.ray.woodencreate.result.MsgCodeConstant;
import com.ray.woodencreate.result.Result;
import com.ray.woodencreate.result.ResultFactory;
import com.ray.woodencreate.util.Assert;
import com.ray.woodencreate.util.LogInUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author bo shen
 * @Description: 角色相关服务
 * @Class: RoleApi
 * @Package com.ray.system.api
 * @date 2020/5/27 11:15
 * @company <p>Ray快速开发平台</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Service
@Slf4j
public class RoleApi {

    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysAppService sysAppService;
    @Autowired
    private SysUserMenuService sysUserMenuService;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private SysUserRoleService sysUserRoleService;


    /**
     * 创建角色
     *
     * @param createParams 创建对象
     * @return Result
     */
    @Transactional
    public Result<String> createRoleForManager(RoleManagerCreateParams createParams) {
        ValidateUtil.validate(createParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();

        SysApp sysApp = sysAppService.queryAppByAppCode(createParams.getAppCode());
        new AppCheck(sysApp).checkNull(SysMsgCodeConstant.Error.ERR10000003);

        SysRole sysRole = sysRoleService.queryRoleByRoleName(createParams.getRoleName(), createParams.getAppCode());
        new RoleCheck(sysRole).checkRoleName(null, SysMsgCodeConstant.Error.ERR10000003);
        RoleBuilder RoleBuilder = new RoleBuilder();
        RoleBuilder.append(createParams).appendStatus(YesOrNoEnum.YES.getValue()).appendCreate(loginUser);
        //保存角色信息
        if (!sysRoleService.save(RoleBuilder.bulid())) {
            log.info("保存角色接口异常,参数:{}", JSON.toJSONString(RoleBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, RoleBuilder.getCode());
    }

    /**
     * 编辑角色
     *
     * @param editParams 编辑对象
     * @return Result
     */
    @Transactional
    public Result<String> editRoleForManager(RoleManagerEditParams editParams) {
        ValidateUtil.validate(editParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();

        SysApp sysApp = sysAppService.queryAppByAppCode(editParams.getAppCode());
        new AppCheck(sysApp).checkNull(SysMsgCodeConstant.Error.ERR10000003);
        SysRole sysRole = sysRoleService.queryRoleByRoleName(editParams.getRoleName(), editParams.getAppCode());
        new RoleCheck(sysRole).checkRoleName(editParams.getRoleName(), SysMsgCodeConstant.Error.ERR10000003);
        RoleBuilder RoleBuilder = new RoleBuilder();
        RoleBuilder.append(editParams).appendEdit(loginUser);
        //编辑角色信息
        if (!sysRoleService.edit(RoleBuilder.bulid(), loginUser)) {
            log.info("编辑角色接口异常,参数:{}", JSON.toJSONString(RoleBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, RoleBuilder.getCode());
    }

    /**
     * 存查询
     * @param queryParams
     * @return
     */
    public Result<IPage<RoleVO>> pageRolesForManager(@Valid CommonPage<RoleManagerQueryParams, Page<RoleVO>> queryParams) {
        Assert.notNull(queryParams, SysMsgCodeConstant.Error.ERR10000001);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        CommonPageBuilder<RoleQueryDTO, SysRole> commonPageBuilder = new CommonPageBuilder<>(RoleQueryDTO.class);
        commonPageBuilder.appendEntity(queryParams.getEntity()).appendQuery(queryParams.getQuery()).appendPage(queryParams.getPage());
        IPage<SysRole> page = sysRoleService.page(commonPageBuilder.bulid(), loginUser);
        List<SysRole> Roles = page.getRecords();
        //结果对象
        IPage<RoleVO> pageList = new Page<>();
        pageList.setTotal(page.getTotal());
        pageList.setCurrent(page.getCurrent());
        pageList.setSize(page.getSize());
        //查询到结果 数据转换
        if (ObjectUtil.isNotNull(Roles)) {
            pageList.setRecords(Roles.stream().map(sysRole -> {
                RoleVO RoleVO = new RoleVO();
                BeanUtil.copyProperties(sysRole, RoleVO);
                return RoleVO;
            }).collect(Collectors.toList()));
        } else {
            pageList.setRecords(new ArrayList<>());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, pageList);
    }


    /**
     * 查询角色列表信息 分页  非删除的
     *
     * @param queryParams
     * @return
     */
    public Result<IPage<RoleVO>> pageRoles(CommonPage<RoleQueryParams, Page<RoleVO>> queryParams) {
        Assert.notNull(queryParams, SysMsgCodeConstant.Error.ERR10000001);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        CommonPageBuilder<RoleQueryDTO, SysRole> commonPageBuilder = new CommonPageBuilder<>(RoleQueryDTO.class);
        commonPageBuilder.appendEntity(queryParams.getEntity()).appendCode(loginUser.getAppCode()).appendQuery(queryParams.getQuery()).appendPage(queryParams.getPage());
        IPage<SysRole> page = sysRoleService.page(commonPageBuilder.bulid(), loginUser);
        List<SysRole> Roles = page.getRecords();
        //结果对象
        IPage<RoleVO> pageList = new Page<>();
        pageList.setTotal(page.getTotal());
        pageList.setCurrent(page.getCurrent());
        pageList.setSize(page.getSize());
        //查询到结果 数据转换
        if (ObjectUtil.isNotNull(Roles)) {
            pageList.setRecords(Roles.stream().map(sysRole -> {
                RoleVO RoleVO = new RoleVO();
                BeanUtil.copyProperties(sysRole, RoleVO);
                return RoleVO;
            }).collect(Collectors.toList()));
        } else {
            pageList.setRecords(new ArrayList<>());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, pageList);
    }

    /**
     * 查询角色列表信息--启用的角色
     *
     * @param queryParams
     * @return
     */
    public Result<List<RoleVO>> queryRoles(RoleQueryParams queryParams) {
        Assert.notNull(queryParams, SysMsgCodeConstant.Error.ERR10000001);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        RoleQueryDTO queryDTO = new RoleQueryDTO();
        BeanUtil.copyProperties(queryParams, queryDTO);
        queryDTO.setStatus(YesOrNoEnum.YES.getValue());
        List<SysRole> Roles = sysRoleService.list(queryDTO, loginUser);
        //查询对象
        List<RoleVO> list = new ArrayList<>();
        if (ObjectUtil.isNotNull(Roles)) {
            list = Roles.stream().map(sysRole -> {
                RoleVO RoleVO = new RoleVO();
                BeanUtil.copyProperties(sysRole, RoleVO);
                return RoleVO;
            }).collect(Collectors.toList());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, list);
    }

    /**
     * 查询角色列表信息--启用的角色
     *
     * @param queryParams
     * @return
     */
    public Result<List<RoleVO>> listForManager(UserRoleQueryParams queryParams) {
        Assert.notNull(queryParams, SysMsgCodeConstant.Error.ERR10000001);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        RoleQueryDTO queryDTO = new RoleQueryDTO();
        BeanUtil.copyProperties(queryParams, queryDTO);
        queryDTO.setStatus(YesOrNoEnum.YES.getValue());
        List<SysRole> Roles = sysRoleService.list(queryDTO, loginUser);

        //查询用户拥有的角色
        List<String> roleCodes =  sysUserRoleService.queryRoleByUserCode(queryParams.getUserCode())
                .stream().map(SysUserRole::getRoleCode).collect(Collectors.toList());
        //查询对象
        List<RoleVO> list = new ArrayList<>();
        if (ObjectUtil.isNotNull(Roles)) {
            list = Roles.stream().map(sysRole -> {
                RoleVO roleVo = new RoleVO();
                BeanUtil.copyProperties(sysRole, roleVo);
                //查询系统
                SysApp sysApp = sysAppService.queryAppByAppCode(sysRole.getAppCode());
                if(ObjectUtil.isNotNull(sysApp)){
                    roleVo.setAppName(sysApp.getAppName());
                }
                roleVo.setAuth(roleCodes.contains(sysRole.getRoleCode()));
                return roleVo;
            }).collect(Collectors.toList());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, list);
    }


    /**
     * 创建角色
     *
     * @param createParams 创建对象
     * @return Result
     */
    @Transactional
    public Result<String> createRole(RoleCreateParams createParams) {
        ValidateUtil.validate(createParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        SysRole sysRole = sysRoleService.queryRoleByRoleName(createParams.getRoleName(), loginUser.getAppCode());
        new RoleCheck(sysRole).checkRoleName(null, SysMsgCodeConstant.Error.ERR10000003);
        RoleBuilder roleBuilder = new RoleBuilder();
        roleBuilder.append(createParams).appendAppCode(loginUser.getAppCode()).appendStatus(YesOrNoEnum.YES.getValue()).appendCreate(loginUser);
        //保存角色信息
        if (!sysRoleService.save(roleBuilder.bulid())) {
            log.info("保存角色接口异常,参数:{}", JSON.toJSONString(roleBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, roleBuilder.getCode());
    }

    /**
     * 编辑角色
     *
     * @param editParams 编辑对象
     * @return Result
     */
    @Transactional
    public Result<String> editRole(RoleEditParams editParams) {
        ValidateUtil.validate(editParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        SysRole sysRole = sysRoleService.queryRoleByRoleName(editParams.getRoleName(), loginUser.getAppCode());
        new RoleCheck(sysRole).checkRoleName(editParams.getRoleName(), SysMsgCodeConstant.Error.ERR10000003);
        RoleBuilder roleBuilder = new RoleBuilder();
        roleBuilder.append(editParams).appendEdit(loginUser);
        //编辑角色信息
        if (!sysRoleService.edit(roleBuilder.bulid(), loginUser)) {
            log.info("编辑角色接口异常,参数:{}", JSON.toJSONString(roleBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, roleBuilder.getCode());
    }


    /**
     * 删除角色
     *
     * @param roleCode 角色编码
     * @return Result
     */
    @Transactional
    public Result<String> deleteRole(String roleCode) {
        ValidateUtil.hasLength(roleCode, "参数[RoleCode]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //获取权限信息
        SysRole sysRole = sysRoleService.queryRoleByRoleCode(roleCode, loginUser);
        new RoleCheck(sysRole).checkNull(SysMsgCodeConstant.Error.ERR10000002).checkDelete(SysMsgCodeConstant.Error.ERR10000002);
        RoleBuilder roleBuilder = new RoleBuilder();
        roleBuilder.appendCode(roleCode).appendEdit(loginUser).delete();
        //删除角色信息
        if (!sysRoleService.edit(roleBuilder.bulid(), loginUser)) {
            log.info("删除角色接口异常,参数:{}", JSON.toJSONString(roleBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, roleBuilder.getCode());
    }

    /**
     * 开启角色
     *
     * @param roleCode 角色编码
     * @return Result
     */
    @Transactional
    public Result<String> openRole(String roleCode) {
        ValidateUtil.hasLength(roleCode, "参数[RoleCode]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //获取权限信息
        SysRole sysRole = sysRoleService.queryRoleByRoleCode(roleCode, loginUser);
        new RoleCheck(sysRole).checkNull(SysMsgCodeConstant.Error.ERR10000002);
        RoleBuilder roleBuilder = new RoleBuilder();
        roleBuilder.appendCode(roleCode).appendEdit(loginUser).open();
        //开启角色信息
        if (!sysRoleService.edit(roleBuilder.bulid(), loginUser)) {
            log.info("开启角色接口异常,参数:{}", JSON.toJSONString(roleBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, roleBuilder.getCode());
    }

    /**
     * 开启角色
     *
     * @param RoleCode 角色编码
     * @return Result
     */
    @Transactional
    public Result<String> closeRole(String RoleCode) {
        ValidateUtil.hasLength(RoleCode, "参数[RoleCode]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //获取权限信息
        SysRole sysRole = sysRoleService.queryRoleByRoleCode(RoleCode, loginUser);
        new RoleCheck(sysRole).checkNull(SysMsgCodeConstant.Error.ERR10000002);
        RoleBuilder roleBuilder = new RoleBuilder();
        roleBuilder.appendCode(RoleCode).appendEdit(loginUser).close();
        //关闭角色信息
        if (!sysRoleService.edit(roleBuilder.bulid(), loginUser)) {
            log.info("关闭角色接口异常,参数:{}", JSON.toJSONString(roleBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, roleBuilder.getCode());
    }

    /**
     * 角色详情
     *
     * @param roleCode 角色编码
     * @return Result
     */
    public Result<RoleVO> viewRole(String roleCode) {
        ValidateUtil.hasLength(roleCode, "参数[roleCode]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //获取权限信息
        SysRole sysRole = sysRoleService.queryRoleByRoleCode(roleCode, loginUser);
        new RoleCheck(sysRole).checkNull(SysMsgCodeConstant.Error.ERR10000002);
        RoleVO roleVO = new RoleVO();
        BeanUtil.copyProperties(sysRole, roleVO);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, roleVO);
    }


    /**
     * 角色授权
     *
     * @param authParams 授权对象
     * @return Result
     */
    @Transactional
    public Result<String> addAuth(RoleAuthParams authParams) {
        ValidateUtil.validate(authParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //查询用户是否拥有该菜单
        //是否拥有全部数据权限
        if (!loginUser.isAllData()) {
            //判断角色是否存在
            SysRole sysRole = sysRoleService.queryRoleByRoleCode(authParams.getRoleCode(), loginUser);
            new RoleCheck(sysRole).checkNull(SysMsgCodeConstant.Error.ERR10000002);
            //判断菜单是否存在
            SysMenu sysMenu = sysMenuService.queryGMenuByMenuCode(authParams.getMenuCode());
            new MenuCheck(sysMenu).checkNull(SysMsgCodeConstant.Error.ERR10000002)
                    .chechSamAppCode(sysRole.getAppCode(), SysMsgCodeConstant.Error.ERR10000008);
            //判断是否有菜单权限
            if (!sysUserMenuService.queryUserHasMenu(loginUser.getUserCode(), authParams.getMenuCode())) {
                log.info("查询菜单权限异常,参数:{}", authParams.getMenuCode());
                throw BusinessExceptionFactory.newException(SysMsgCodeConstant.Error.ERR10000010);
            }
        }
        UserMenuBuilder userMenuBuilder = new UserMenuBuilder();
        userMenuBuilder.append(authParams).appendCreate(loginUser);
        //角色菜单关联
        if (!sysUserMenuService.save(userMenuBuilder.bulid())) {
            log.info("角色菜单关联接口异常,参数:{}", JSON.toJSONString(userMenuBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, "");
    }

    /**
     * 删除角色授权
     *
     * @param authParams 授权对象
     * @return Result
     */
    @Transactional
    public Result<String> removeAuth(RoleAuthParams authParams) {
        ValidateUtil.validate(authParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //是否拥有全部数据权限
        if (!loginUser.isAllData()) {
            //判断是否有角色权限
            if (!sysUserRoleService.queryUserHasRole(loginUser.getUserCode(), authParams.getRoleCode())
                    && ObjectUtil.isNull(sysRoleService.queryRoleByRoleCode(authParams.getRoleCode(),loginUser))) {
                log.info("查询角色权限异常,参数:{}", authParams.getRoleCode());
                throw BusinessExceptionFactory.newException(SysMsgCodeConstant.Error.ERR10000011);
            }
        }
        UserMenuBuilder userMenuBuilder = new UserMenuBuilder();
        userMenuBuilder.append(authParams).appendEdit(loginUser).delete();
        //删除角色菜单关联
        if (!sysUserMenuService.delete(userMenuBuilder.bulid(), loginUser)) {
            log.info("删除角色菜单关联接口异常,参数:{}", JSON.toJSONString(userMenuBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, "");
    }



}
